<?php
namespace app\api\controller;

use think\Controller;
use think\Db;
use think\Cache;
use think\Config;
use think\Response;


class Common extends Controller
{
    protected $result = array('success'=> true,'errorCode' => 0, 'errorMsg' => '');
    protected $uid = 0;
    protected $oracleDb;
    /*  动作名称全部小写 */
    protected $noLoginAction = array(
        'Index' => array(
            'regionList',
        ),
    );
    public function ajax_return($result=[]){
        if(empty($result)){
            $result = $this->result;
        }
        return Response::create($result, 'json');
    }
    public function _initialize()
    {
        $origin = isset($_SERVER['HTTP_ORIGIN']) ? $_SERVER['HTTP_ORIGIN'] : '';

        $allow_origin = array(
            'http://bhgt.jslcwy.com',
            'http://localhost',
            'http://localhost:8080',
            'https://open.weixin.qq.com', //微信登录回调
            'http://127.0.0.1',
	        'http://127.0.0.1:8020',
            ''
        );
        if (in_array($origin, $allow_origin)) {
            header('Access-Control-Allow-Origin:' . $origin);
            header('Access-Control-Allow-Methods:POST');
            header('Access-Control-Allow-Headers:x-requested-with,content-type');
        } else {
            $this->result['error'] = 99;
            $this->result['msg'] = '非法请求' . $origin . '非法请求';
            $this->ajaxReturn($this->result);

        }
        file_put_contents('uploads/request.txt', date('Y-m-d H:i:s') . ' ' . $this->request->controller() . ' /' . $this->request->action() . ' ' . json_encode(input('request.')) . ' FILE ' . json_encode($this->request->file()) . PHP_EOL, FILE_APPEND);
        if (in_array($this->request->action(), $this->noLoginAction[$this->request->controller()]) && !$this->checkLogin()) {
            $this->ajaxReturn($this->result);
        }

        parent::_initialize();


    }


    public function syncQueue($flush = false)
    {
        $branchLists = model('BranchList')->where(['isdelete' => 0])->column('id,db_info');
//        shuffle($branchLists);
        foreach ($branchLists as $branchId => $branchInfo) {
            // 初次同步 初始化缓存
            if (!Cache::has('syncOracleQueue' . $branchId)) {
                Cache::set('syncOracleQueue' . $branchId, 1, 0);
            }

            $syncQueueTime = Cache::get('syncOracleQueue' . $branchId);
            if (($syncQueueTime && NOW_TIME - $syncQueueTime > Config::get('syncTime')) || $flush) {
                $syncQueueTime = $syncQueueTime ?: '0';
                $lastQueueDate = date('Y-m-d H:i:s', $syncQueueTime);

                $this->getOracleDb($branchId);

                if ($this->result['error']) {
                    continue;
                }

                //同步队列新数据
                $sql = "select ID, SERVICE, CODE, to_char(FCD,'yyyy-mm-dd hh24:mi:ss') FCDFORMATE from QUEUE" .
                    " where FCD>to_date('" . $lastQueueDate . "','yyyy-mm-dd hh24:mi:ss')";
                $syncQueueLists = $this->oracleDb->query($sql);
                if ($syncQueueLists) {
                    $queueModel = model('Queue');
                    foreach ($syncQueueLists as $key => $syncQueueList) {
                        $insertQueue = $queueModel->field(true)->where(['queue_sn' => $syncQueueList['ID']])->find();

                        if (!$insertQueue) {
                            $boolean = $queueModel->insert([
                                'queue_sn' => $syncQueueList['ID'],
                                'branchid' => $branchId,
                                'serviceid' => $this->getLocalServiceId($branchId, $syncQueueList['SERVICE']),
                                'bisid' => 0,
                                'type' => 3,  //线下排队
                                'queue_time' => strtotime($syncQueueList['FCDFORMATE']),
                                'queue_code' => $syncQueueList['CODE'],
                                'create_time' => NOW_TIME
                            ]);
                        }
                    }
                }

                //同步历史
                $sql = "select ID, CODE, SERVICE,to_char(FCD,'yyyy-mm-dd hh24:mi:ss') FCDFORMATE, " .
                    "to_char(SSD,'yyyy-mm-dd hh24:mi:ss') SSDFORMATE,to_char(LCD,'yyyy-mm-dd hh24:mi:ss') LCDFORMATE " .
                    " from QUEUE_HISTORY where LCD>to_date('" . $lastQueueDate . "','yyyy-mm-dd hh24:mi:ss')";
                $syncQueueHisLists = $this->oracleDb->query($sql);
                if ($syncQueueHisLists) {
                    $queueHisModel = model('QueueHistory');
                    $queueModel = model('Queue');
                    foreach ($syncQueueHisLists as $key => $syncQueueHisList) {
                        $insertQueue = $queueHisModel->field(true)->where(['queue_sn' => $syncQueueHisList['ID']])->find();
                        $queueInfo = $queueModel->where('queue_sn', $syncQueueHisList['ID'])->find();
                        if (!$insertQueue) {
                            $boolean = $queueHisModel->insert();
                            $queueHisData = array(
                                'queue_sn' => $syncQueueHisList['ID'],
                                'queue_code' => $syncQueueHisList['CODE'],
                                'branchid' => isset($queueInfo->branchid) ? $queueInfo->branchid : $branchId,
                                'serviceid' => $this->getLocalServiceId($queueInfo->branchid, $syncQueueHisList['SERVICE']),
                                'bisid' => isset($queueInfo->bisid) ? $queueInfo->bisid : 0,
                                'type' => isset($queueInfo->type) ? $queueInfo->type : 3,  //线下排队
                                'uid' => isset($queueInfo->uid) ? $queueInfo->uid : 0,
                                'truename' => isset($queueInfo->truename) ? $queueInfo->truename : 0,
                                'mobile' => isset($queueInfo->mobile) ? $queueInfo->mobile : 0,
                                'queue_time' => strtotime($syncQueueHisList['FCDFORMATE']),
                                'handle_start_time' => strtotime($syncQueueHisList['SSDFORMATE']),
                                'handle_end_time' => strtotime($syncQueueHisList['LCDFORMATE']),
                                'create_time' => NOW_TIME
                            );
                            $queueHisData['queue_status'] = $queueHisData['handle_start_time'] == $queueHisData['handle_end_time'] ? 2 : 3;
                            $boolean = $queueHisModel->insert($queueHisData);
                        } else {
                            $queueHisModel->where(['id' => $insertQueue['id']])->update(['queue_status' => 3, 'handle_end_time' => strtotime($syncQueueHisList['LCDFORMATE'])]);
                        }
                        $queueModel->where('queue_sn', $syncQueueHisList['ID'])->delete();
                    }
                }

                Cache::set('syncOracleQueue' . $branchId, NOW_TIME, 0);
            }
            return;
        }
    }

    /**
     * 获取pdo oracle数据 实例
     * @param $bisId
     * @return \think\Response|\think\response\Json|\think\response\Jsonp|\think\response\Redirect|\think\response\View|\think\response\Xml
     */
    public function getOracleDb($branchId)
    {

        //获取此业务的名称
        $db_info = model('BranchList')->where('id', $branchId)->value('db_info');
        $db_info = json_decode(htmlspecialchars_decode($db_info), true);
        try {
            $this->oracleDb = Db::connect($db_info);
            $this->oracleDb->table('SERVICE')->where(['CODE' => 'A'])->value('ID');
            $this->result['error'] = 0;
        } catch (\PDOException $pdoExp) {
            $this->result['error'] = 1;
            $this->result['msg'] = 'oracle 初始化失败';
            return ajax_return_error($pdoExp->getMessage());
        }

    }

    /**
     * 获取远程oracle 服务id
     * @param $oracleDb
     * @param $code  服务code
     * @return string
     */
    public function getRemoteServiceId($branchId, $code)
    {
        static $remoteServiceList;
        if (!$branchId || !$code) {
            return '';
        }
        if (empty($remoteServiceList)) {
            $remoteServiceList = Cache::get('remoteServiceList' . $branchId);
        }
        if (!isset($remoteServiceList[$code])) {

            $this->getOracleDb($branchId);

            $id = $this->oracleDb->table('SERVICE')->where(['CODE' => $code])->value('ID');

            if (!$id) {
                $this->result['error'] = 1;
                $this->result['msg'] = '编码匹配出错或连接失败';
                return;
//                $this->ajaxReturn($this->result);
            }
            $remoteServiceList[$code] = $id;

            Cache::set('remoteServiceList' . $branchId, $remoteServiceList);

        }
        return $remoteServiceList[$code];
    }

    /**
     * 远程 serviceId 获取本地的 serviceId
     * @param $oracleDb
     * @param $remoteServiceId
     * @return string
     */
    public function getLocalServiceId($branchId, $remoteServiceId)
    {
        static $serviceList;
        /* 非法参数 */
        if (empty($remoteServiceId) || empty($branchId)) {
            return '';
        }
        if (empty($serviceList)) {
            $serviceList = Cache::get('syncServiceList' . $branchId);
        }
        if (!isset($serviceList[$remoteServiceId])) {
            $this->getOracleDb($branchId);
            $code = $this->oracleDb->table('SERVICE')->where(['ID' => $remoteServiceId])->value('CODE');
            if (!$code) { //不存在
                $this->result['error'] = 1;
                $this->result['msg'] = '编码匹配出错或连接失败';
                $this->ajaxReturn($this->result);
            }
            $bCateModel = model('BusinessCategory');
            $localServiceId = $bCateModel->where('code', $code)->value('id');
            $serviceList[$remoteServiceId] = $localServiceId;

            Cache::set('syncServiceList' . $branchId, $serviceList);

        }
        return $serviceList[$remoteServiceId]?:0;
    }

    /**
     * 远程 serviceId 获取本地的 serviceId
     * @param $branchId
     * @param $bisId
     * @return string
     */
    public function checkOrderQueueTime($branchId, $bisId, $orderTimestamp)
    {
        /* 非法参数 */
        if (empty($branchId) || empty($bisId)) {
            $this->result['error'] = 1;
            $this->result['msg'] = '参数有误';
            return false;
        }

        $branchInfo = model('BranchList')->where(['id' => $branchId])->find();
        //判断预约日期是否开放
        $branchInfo->times = json_decode(htmlspecialchars_decode($branchInfo->times), true);
        $queueTime = $branchInfo->times['content'][date('N', $orderTimestamp) - 1];
        if ($queueTime['status'] == 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '日期未开放';
            return false;
        }

        //判断预约时间是否开放
        $formateDate = date('Y-m-d ', $orderTimestamp);
        $timePass = 0;
        foreach ($queueTime['times'] as $dayTime) {
            $startTime = strtotime($formateDate . $dayTime['start']);
            $endTime = strtotime($formateDate . $dayTime['end']);
            if ($orderTimestamp >= $startTime && $orderTimestamp <= $endTime) {
                $timePass = 1;
                break;
            }
            continue;
        }
        if ($timePass == 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '时间未开放';
            return false;
        }


        $startTime = strtotime($formateDate);
        $endTime = $startTime + 3600 * 24;
        $allowNum = model('BranchBusiness')->where(['bisid' => $bisId, 'branchid' => $branchId])->value('allownum');
        $queueNum = model('Queue')->where(['bisid' => $bisId, 'branchid' => $branchId, 'status' => 1])->count(1) ?: 0;
        $queueHisNum = model('QueueHistory')->where(['bisid' => $bisId, 'branchid' => $branchId,
            'type' => ['in', [1, 2]], 'status' => 1, 'queue_time' => ['>', $startTime]])->count(1) ?: 0;
        $queueOrderNum = model('QueueOrder')->where(['bisid' => $bisId, 'branchid' => $branchId,
            'status' => 1, 'queue_time' => [['>', $startTime], ['<', $endTime]]])->count(1) ?: 0;
        if ($allowNum <= $queueNum + $queueHisNum + $queueOrderNum) {
            $this->result['error'] = 1;
            $this->result['msg'] = '暂无名额' . '+' . $queueNum . '+' . $queueHisNum . '+' . $queueOrderNum;
            return false;
        }

        $queueOrderNum = model('QueueOrder')->where(['branchid' => $branchId, 'status' => 1, 'uid' => $this->uid,
            'queue_time' => [['>', $startTime], ['<', $endTime]]])->count(1) ?: 0;
        if ($queueOrderNum > 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '不可多次排队';
            return false;
        }
        $queueNum = model('Queue')->where(['branchid' => $branchId, 'status' => 1, 'uid' => $this->uid,
            'queue_time' => [['>', $startTime], ['<', $endTime]]])->count(1) ?: 0;
        if ($queueNum > 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '不可多次排队';
            return false;
        }

        return true;
    }

    /**
     * 远程 serviceId 获取本地的 serviceId
     * @param $branchId
     * @param $bisId
     * @return string
     */
    public function checkOrderQueueTimeNew($branchId, $bisId, $orderTimestamp)
    {
        /* 非法参数 */
        if (empty($branchId) || empty($bisId)) {
            $this->result['error'] = 1;
            $this->result['msg'] = '参数有误';
            return false;
        }

        $calendarInfo = model('Calendar')->where(['status' => 1, 'isdelete' => 0])->find();

        //判断预约日历日期是否开放
        $calendarInfo->times = json_decode(htmlspecialchars_decode($calendarInfo->times), true);
        if (isset($calendarInfo->times[date('Y-m-d', $orderTimestamp)])) {
            $this->result['error'] = 1;
            $this->result['msg'] = '日期未开放';
            return false;
        }


        $branchInfo = model('BranchList')->where(['id' => $branchId])->find();
        //判断预约日期是否开放
        $branchInfo->times = json_decode(htmlspecialchars_decode($branchInfo->times), true);
        if (isset($branchInfo->times[date('Y-m-d', $orderTimestamp)])) {
            $this->result['error'] = 1;
            $this->result['msg'] = '日期未开放';
            return false;
        }

//        $queueTime = json_decode(htmlspecialchars_decode($branchInfo->times), true);$calendarInfo->times;
        $queueTime = Config::get('queue_time');

        //判断预约时间是否开放
        $formatDate = date('Y-m-d ', $orderTimestamp);
        $timePass = 0;
        foreach ($queueTime as $dayTime) {
            $startTime = strtotime($formatDate . $dayTime['start']);
            $endTime = strtotime($formatDate . $dayTime['end']);
            if ($orderTimestamp >= $startTime && $orderTimestamp <= $endTime) {
                $timePass = 1;
                break;
            }
            continue;
        }

        if ($timePass == 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '时间未开放';
            return false;
        }

        $queueOrderNum = model('QueueOrder')->where(['bisid' => $bisId, 'branchid' => $branchId,
            'status' => 1, 'queue_time' => $orderTimestamp])->count(1) ?: 0;
        if ($queueOrderNum >= 1) {   //半小时只允许预约一个人，可选择的时间粒度为半小时
            $this->result['error'] = 1;
            $this->result['msg'] = '当前时间已约满';
            return false;
        }

        $startTime = strtotime($formatDate);
        $endTime = $startTime + 3600 * 24;
        $queueNum = model('Queue')->where(['bisid' => $bisId, 'branchid' => $branchId, 'status' => 1])->count(1) ?: 0;
        $queueHisNum = model('QueueHistory')->where(['bisid' => $bisId, 'branchid' => $branchId,
            'type' => ['in', [1, 2]], 'status' => 1, 'queue_time' => ['>', $startTime]])->count(1) ?: 0;
        $queueOrderNum = model('QueueOrder')->where(['bisid' => $bisId, 'branchid' => $branchId,
            'status' => 1, 'queue_time' => [['>', $startTime], ['<', $endTime]]])->count(1) ?: 0;
        if ($branchInfo->num <= $queueNum + $queueHisNum + $queueOrderNum) {
            $this->result['error'] = 1;
            $this->result['msg'] = '暂无名额' . '+' . $queueNum . '+' . $queueHisNum . '+' . $queueOrderNum;
            return false;
        }


        $queueOrderNum = model('QueueOrder')->where(['branchid' => $branchId, 'status' => 1, 'uid' => $this->uid,
            'queue_time' => [['>', $startTime], ['<', $endTime]]])->count(1) ?: 0;
        if ($queueOrderNum > 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '不可多次排队';
            return false;
        }
        $queueNum = model('Queue')->where(['branchid' => $branchId, 'status' => 1, 'uid' => $this->uid,
            'queue_time' => [['>', $startTime], ['<', $endTime]]])->count(1) ?: 0;
        if ($queueNum > 0) {
            $this->result['error'] = 1;
            $this->result['msg'] = '不可多次排队';
            return false;
        }

        return true;
    }

    /**
     * 下一个可预约的日期
     * @param $branchId
     * @param string $orderDay 空或者具体日期
     * @param int $next {-1 ,1}
     * @return string  返回下一个可预约的日期
     */
    public function findOrderDay($branchId, $orderDay = '', $next = 1)
    {

        $branchInfo = model('BranchList')->where(['id' => $branchId])->find();
        $branchInfo->times = json_decode(htmlspecialchars_decode($branchInfo->times), true);
        $calendarInfo = model('Calendar')->where(['status' => 1, 'isdelete' => 0])->find();
        $calendarInfo->times = json_decode(htmlspecialchars_decode($calendarInfo->times), true);
        $orderDay = empty($orderDay) ? strtotime(date('Y-m-d')) : strtotime($orderDay);    //  当前日期
        $exceptDates = array_merge((array)$calendarInfo->times, (array)$branchInfo->times);
        $allowDay = date('Y-m-d');
        for ($i = 0; $i < $branchInfo->days; $i++) {
            $allowDay++;
            if (in_array($allowDay, $exceptDates)) {
                $i--;
            }
        }
        while (1) {

            $nextDay = $orderDay + $next * 3600 * 24;   //明日时间戳
            $next > 0 ? ++$next : --$next;
            //判断预约日历日期是否开放
            $nextDayFormat = date('Y-m-d', $nextDay);

            if (in_array($nextDayFormat, $exceptDates)) {
                $this->result['error'] = 1;
                $this->result['msg'] = '日期未开放';
                continue;
            }

            if ($nextDay <= strtotime(date('Y-m-d'))) {
                $this->result['error'] = 1;
                $this->result['msg'] = '不可预约今日或过去的时间';
                return false;
            }

            // 获取当日时间 不超过 $branchInfo->days 限定天数
            if ($allowDay < $nextDayFormat) {
                $this->result['error'] = 1;
                $this->result['msg'] = '不可预约过远的时间';
                return false;
            }

            return $nextDayFormat;
        }
        return false;
    }

    /**
     * 获取当前登录的用户uid
     * @return int
     */
    public function getUid()
    {
        if (!empty($this->uid)) {
            return $this->uid;
        } else {
            $this->checkLogin();
            return $this->uid;
        }
    }

    /**
     * uuid登录验证
     * @return boolean
     */
    protected function checkLogin()
    {
        $uuid = input('uuid');
        if (empty($uuid)) {
            $this->result['error'] = 103;
            $this->result['msg'] = 'uuid不能为空！';
            return false;
        }

        $this->uid = model("Member")->loginUuid($uuid, false);

        if (0 > $this->uid) { //错误
            switch ($this->uid) {
                case -1:
                    $this->result['error'] = 101;
                    $this->result['msg'] = '用户不存在或已禁用！';
                    break; //系统级别禁用
                case -2:
                    $this->result['error'] = 102;
                    $this->result['msg'] = 'uuid已过期！';
                    break;
                default:
                    $this->result['error'] = 100;
                    $this->result['msg'] = 'uuid未知错误！';
                    break;
            }
            return false;
        } else {
            return true;
        }
    }

    /**
     * Ajax方式返回数据到客户端
     * @access protected
     * @param mixed $data 要返回的数据
     * @param String $type AJAX返回数据格式
     * @param int $json_option 传递给json_encode的option参数
     * @return void
     */
    protected function ajaxReturn($data, $type = '', $json_option = 0)
    {
        if (empty($type)) $type = Config::get('default_ajax_return');
        switch (strtoupper($type)) {
            case 'JSON' :
                // 返回JSON数据格式到客户端 包含状态信息
                header('Content-Type:application/json; charset=utf-8');
                $data = json_encode($data, $json_option);
                break;
            case 'JSONP':
                // 返回JSON数据格式到客户端 包含状态信息
                header('Content-Type:application/json; charset=utf-8');
                $handler = isset($_GET[Config::get('var_jsonp_handler')]) ? $_GET[Config::get('VAR_JSONP_HANDLER')] : Config::get('default_jsonp_handler');
                $data = $handler . '(' . json_encode($data, $json_option) . ');';
                break;
            case 'EVAL' :
                // 返回可执行的js脚本
                header('Content-Type:text/html; charset=utf-8');
                break;
        }
        exit($data);
    }
}
